#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
using namespace std;

#define CONSTRAINT 100

class Electron {

protected:

  int x ;
  int y ;

  virtual void checkConstraint( ) ;
  virtual unsigned int getRandom( ) { return rand( ) % 4 ; }

public:

  Electron( ) { x = 0; y = 0 ; }
  virtual void move( ) ;
  virtual void display( ostream &os ) ;
  static void initSeed( ) { srand( ( unsigned ) time( NULL ) ) ; }
  static void initSeed( unsigned int seed ) { srand( seed ) ; }

} ;

void Electron::move( ) {

  switch( getRandom( ) ) {
    case 0:
      x++ ;
      break ;
    case 1:
      x-- ;
      break ;
    case 2:
      y++ ;
      break ;
    case 3:
      y-- ;
      break ;
    default:
      break ;
  }

  checkConstraint( ) ;

}

void Electron::checkConstraint( ) {

  if( x > CONSTRAINT )
    x = - CONSTRAINT ;
  if( x < - CONSTRAINT )
    x = CONSTRAINT ;
  if( y > CONSTRAINT )
    y = - CONSTRAINT ;
  if( y < - CONSTRAINT )
    y = CONSTRAINT ;

}

void Electron::display( ostream &os ) {
  os << x << "," << y << endl ;
}

void output( Electron *e[], unsigned int element_num, unsigned int step ) {

  char output_file[20] ;

  sprintf( output_file, "%06d.csv", step ) ;
  ofstream ofs( output_file ) ;
  if( ofs ) {
    for( unsigned int i = 0; i < element_num; i++ )
      e[ i ]->display( ofs ) ;
    cout << "[info] " << output_file << " was generated." << endl ;
  } else {
    cout << "[error] " << output_file << " can't open." << endl ;
  }

}

int main( int argc, char **argv ) {

  if( argc != 4 ) {
    cout << "usage : " << argv[ 0 ] << " <element#> <loop#> <step>" << endl ;
    return -1 ;
  }

  char output_file[20] ;

  // need to validate arguments.
  unsigned int element_num = atoi( argv[ 1 ] ) ;
  unsigned int loop = atoi( argv[ 2 ] ) ;
  unsigned int step = atoi( argv[ 3 ] ) ;

  Electron *e[ element_num ] ;
  unsigned int i, j ;

  Electron::initSeed( ) ;

  for( i = 0; i < element_num; i++ )
    e[ i ] = new Electron[ element_num ] ;

  output( e, element_num, 0 ) ;

  for( i = 0; i < loop + 1; i++ ) {

    for( j = 0; j < element_num; j++ ) {
      e[ j ]->move( ) ;
    }

    if( i % step == step - 1 ) {
      output( e, element_num, i + 1 ) ;
    }

  }

  for( i = 0; i < element_num; i++ )
    delete e[ i ] ;

  return 0 ;

}

